package cn.com.bod.fas.common.utils;

import com.github.pagehelper.Page;
import org.springframework.beans.BeanUtils;
import org.springframework.lang.Nullable;

import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;

/**
 * @description vo装换工具类
 * @author zhangchi
 * @date 2019年9月23日 15:29:18
 * @version 1.0.0
 * @Copyright (c) scfhdt
 */
public class VoTransformUtil {

    /**
     * @description 对象属性复制
     * @author zhangchi
     * @date 2019年9月23日 15:29:47
     * @param source 源对象
     * @param supplier 复制对象生成函数
     * @return T 复制后对象
     */
    public static <T> T beanCopy(@Nullable Object source, Supplier<T> supplier) {
        return beanCopy(source, supplier, null);
    }

    /**
     * @description 对象属性复制, 数据源为null时将返回一个新建无数据对象
     * @author zhangchi
     * @date 2019年9月23日 15:46:58
     * @param source 源对象
     * @param supplier 复制对象生成函数
     * @param ignoreProperties 复制忽略属性数组
     * @return T 复制后对象
     */
    public static <T> T beanCopy(@Nullable Object source, Supplier<T> supplier, String[] ignoreProperties) {
        T target = supplier.get();
        if(source != null) {
            BeanUtils.copyProperties(source, target, ignoreProperties);
        }
        return target;
    }

    /**
     * @description 对象属性复制，复制源为空时，返回null
     * @author zhangchi
     * @date 2019年10月22日 09:14:26
     * @param source
     * @param supplier
     * @return T
     */
    public static <T> T beanCopyNull(@Nullable Object source, Supplier<T> supplier) {
        return beanCopyNull(source, supplier, null);
    }

    /**
     * @description 对象属性复制，复制源为空时，返回null
     * @author zhangchi
     * @date 2019年10月22日 09:14:26
     * @param source
     * @param supplier
     * @param ignoreProperties
     * @return T
     */
    public static <T> T beanCopyNull(@Nullable Object source, Supplier<T> supplier, String[] ignoreProperties) {
        T target = null;
        if (source != null) {
            target = supplier.get();
            BeanUtils.copyProperties(source, target, ignoreProperties);
        }
        return target;
    }

    /**
     * @description 集合复制-转换函数
     * @author zhangchi
     * @date 2019年9月30日 15:23:51
     * @param source 复制源
     * @param function 转换函数
     * @return java.util.List<T>
     */
    public static <T, E> List<T> listCopy(List<E> source, Function<E, T> function) {
        return source.stream()
                .map(function)
                .collect(Collectors.toList());
    }

    /**
     * @description 复制集合
     * @author zhangchi
     * @date 2019年9月23日 15:47:42
     * @param source 复制源
     * @param supplier 复制对象生成函数
     * @return java.util.List<T> 复制后集合
     */
    public static <T, E> List<T> listCopy(List<E> source, Supplier<T> supplier) {
        return listCopy(source, e -> beanCopy(e, supplier));
    }

    /**
     * @description 复制集合
     * @author zhangchi
     * @date 2019年9月23日 15:47:42
     * @param source 复制源
     * @param supplier 复制对象生成函数
     * @param ignoreProperties 复制忽略属性数组
     * @return java.util.List<T> 复制后集合
     */
    public static <T, E> List<T> listCopy(List<E> source, Supplier<T> supplier, String[] ignoreProperties) {
        return listCopy(source, e -> beanCopy(e, supplier, ignoreProperties));
    }

    /**
     * @description 集合复制
     * @author zhangchi
     * @date 2019年9月30日 15:24:09
     * @param source 复制源
     * @param supplier 生成函数
     * @param consumer 转换函数
     * @return java.util.List<T>
     */
    public static <T, E> List<T> listCopy(List<E> source, Supplier<T> supplier, Consumer<T> consumer) {
        return listCopy(source, e -> {
            T t = beanCopy(e, supplier);
            consumer.accept(t);
            return t;
        });
    }

    /**
     * @description list转换-生成函数+转换函数+忽略复制属性
     * @author zhangchi
     * @date 2019年9月30日 16:00:33
     * @param source 复制源
     * @param supplier 生成函数
     * @param consumer 转换函数
     * @param ignoreProperties 忽略属性
     * @return java.util.List<T>
     */
    public static <T, E> List<T> listCopy(List<E> source, Supplier<T> supplier, Consumer<T> consumer, String[] ignoreProperties) {
        return listCopy(source, e -> {
            T t = beanCopy(e, supplier, ignoreProperties);
            consumer.accept(t);
            return t;
        });
    }

    /**
     * @description page转换 - 转换函数
     * @author zhangchi
     * @date 2019年9月30日 15:29:47
     * @param source 复制源
     * @param function 转换函数
     * @return java.util.List<T>
     */
    public static <T, E> List<T> pageCopy(List<E> source, Function<E, T> function) {
        Page<T> target = new Page<>();
        target.setTotal(((Page)source).getTotal());
        source.stream().map(function).forEach(target::add);
        return target;
    }

    /**
     * @description page转换
     * @author zhangchi
     * @date 2019年9月27日 12:24:57
     * @param source 分页数据源
     * @param supplier 复制对象生成函数
     * @return java.util.List<T> 复制后page对象
     */
    public static <T, E> List<T> pageCopy(List<E> source, Supplier<T> supplier) {
        return pageCopy(source, e -> beanCopy(e, supplier));
    }

    /**
     * @description page转换 - 生成函数
     * @author zhangchi
     * @date 2019年9月27日 12:24:57
     * @param source 分页数据源
     * @param supplier 复制对象生成函数
     * @param ignoreProperties 复制忽略属性数组
     * @return java.util.List<T> 复制后page对象
     */
    public static <T, E> List<T> pageCopy(List<E> source, Supplier<T> supplier, @Nullable String[] ignoreProperties) {
        return pageCopy(source, e -> beanCopy(e, supplier, ignoreProperties));
    }

    /**
     * @description page转换-生成函数+转换函数
     * @author zhangchi
     * @date 2019年9月30日 15:39:09
     * @param source 复制源
     * @param supplier 生成函数
     * @param consumer 转换函数
     * @return java.util.List<T> 
     */
    public static <T, E> List<T> pageCopy(List<E> source, Supplier<T> supplier, Consumer<T> consumer) {
       return pageCopy(source, e -> {
           T t = beanCopy(e, supplier);
           consumer.accept(t);
           return t;
       });
    }

    /**
     * @description page转换 - 生成函数 + 转换函数 + 忽略属性
     * @author zhangchi
     * @date 2019年9月30日 16:02:17
     * @param source 源数据
     * @param supplier 生成函数
     * @param consumer 转换函数
     * @param ignoreProperties 忽略属性
     * @return java.util.List<T>
     */
    public static <T, E> List<T> pageCopy(List<E> source, Supplier<T> supplier, Consumer<T> consumer, String[] ignoreProperties) {
        return pageCopy(source, e -> {
            T t = beanCopy(e, supplier, ignoreProperties);
            consumer.accept(t);
            return t;
        });
    }

    private VoTransformUtil() {
        throw new IllegalStateException("Utility class");
    }

}
